package com.cls.business.controller;

import com.cls.business.entity.*;
import com.cls.business.service.*;
import com.cls.business.service.impl.ExportExcelService;
import com.cls.business.vo.DeclareTopicVO;
import com.cls.business.vo.SelectEntrustVO;
import com.cls.business.vo.SummaryDeclareTopic;
import com.cls.common.annotation.ControllerEndpoint;
import com.cls.common.controller.BaseController;
import com.cls.common.entity.MyConstant;
import com.cls.common.entity.QueryRequest;
import com.cls.common.entity.ResponseVO;
import com.cls.common.enums.DictEnum;
import com.cls.common.enums.MessageEnum;
import com.cls.common.utils.DateUtil;
import com.cls.common.utils.FileUtil;
import com.cls.common.utils.MyUtil;
import com.cls.common.utils.StringUtils;
import com.cls.system.entity.*;
import com.cls.system.service.*;
import com.github.pagehelper.PageInfo;
import com.wuwenze.poi.ExcelKit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.*;

/**
 * 申报课题表 Controller
 *
 * @author weimaomao
 * @date 2020-11-10 11:09:57
 */
@Slf4j
@Validated
@Controller
@RequiredArgsConstructor
public class DeclareTopicController extends BaseController {

    private final IDeclareTopicService declareTopicService;

    private final ISysDictService sysDictService;

    private final IApplicantInfoService applicantInfoService;

    private final IConfigureService configureService;

    private final ITopicPlanService topicPlanService;

    private final ITopicService topicService;

    private final IMemberInfoService memberInfoService;

    private final IMessageService messageService;

    private final IDeclarePlanService declarePlanService;

    private final ISysFileService sysFileService;

    private final ITemplateService templateService;

    private final ILogDeclareTopicService logDeclareTopicService;

    @GetMapping(MyConstant.VIEW_PREFIX + "biz/declareTopic")
    public String declareTopicIndex(Model model){
        List<SysDict> subjectTypes = sysDictService.findByParentCode(DictEnum.SUBJECT_TYPE.getCode());
        List<SysDict> statusTypes = sysDictService.findByParentCode(DictEnum.TOPIC_STATUS.getCode());
        model.addAttribute("subjectTypes",subjectTypes);
        model.addAttribute("statusTypes",statusTypes);
        return MyUtil.view("business/declareTopic/list");
    }

/*    @GetMapping("declareTopic")
    @ResponseBody
    @RequiresPermissions("declareTopic:list")
    public ResponseVO getAllDeclareTopics(DeclareTopic declareTopic) {
        return ResponseVO.success(declareTopicService.findDeclareTopics(declareTopic));
    }*/

    @GetMapping("declareTopic/list")
    @ResponseBody
//    @RequiresPermissions("declareTopic:list")
    public ResponseVO declareTopicList(QueryRequest request, DeclareTopic declareTopic) {
        User user = getCurrentUser();
        if(user == null){
            throw new IllegalArgumentException("获取用户失败！");
        }
        if(DictEnum.ROLE_DECLARE.getCode().equals(user.getRoleTypeCode()) || DictEnum.ROLE_EXPERT.getCode().equals(user.getRoleTypeCode())){
            declareTopic.setCreateBy(user.getId());
        }
        declareTopic.setTopicClassifyCode(DictEnum.ANNUAL.getCode());
        PageInfo<DeclareTopicVO> pageInfo =  this.declareTopicService.findDeclareTopics(request, declareTopic);
        return ResponseVO.success(pageInfo);
    }



/*    @GetMapping("declareTopic/client/list")
    @ResponseBody
//    @RequiresPermissions("declareTopic:list")
    public ResponseVO declareClientTopicList(QueryRequest request, DeclareTopic declareTopic) {
        User user = getCurrentUser();
        if(user == null){
            throw new IllegalArgumentException("获取用户失败！");
        }
//        if(!DictEnum.ROLE_DECLARE.getCode().equals(user.getRoleTypeCode())){
//            declareTopic.setCreateBy(user.getId());
//        }
        PageInfo<DeclareTopicVO> pageInfo =  this.declareTopicService.findDeclareTopics(request, declareTopic);
        return ResponseVO.success(pageInfo);
    }*/


    @ControllerEndpoint(operation = "新增课题申报", exceptionMessage = "新增课题申报失败")
    @PostMapping("declareTopic")
    @ResponseBody
//    @RequiresPermissions("declareTopic:add")
    public ResponseVO addDeclareTopic(@RequestBody DeclareTopicVO declareTopicVO) {
        if(declareTopicVO.getTopicId() == null){
            return ResponseVO.failure("课题指南不能为空！");
        }
        ApplicantInfo applicantInfo = declareTopicVO.getLeader();
        if(applicantInfo.getApplicantId() == null) {
            return ResponseVO.failure("主持人ID为空！");
        }
        declareTopicService.createDeclareTopic(declareTopicVO);
        return ResponseVO.success("新增课题申报成功！");
    }

    @ControllerEndpoint(operation = "删除课题申报", exceptionMessage = "删除课题申报失败")
    @GetMapping("declareTopic/delete")
    @ResponseBody
//    @RequiresPermissions("declareTopic:delete")
    public ResponseVO deleteDeclareTopic(DeclareTopic declareTopic) {
        this.declareTopicService.deleteDeclareTopic(declareTopic);
        return ResponseVO.success("删除成功！");
    }

    @ControllerEndpoint(operation = "修改课题申报", exceptionMessage = "修改课题申报失败")
    @PostMapping("declareTopic/update")
    @ResponseBody
//    @RequiresPermissions("declareTopic:update")
    public ResponseVO updateDeclareTopic(@RequestBody DeclareTopicVO declareTopic) {
        this.declareTopicService.updateDeclareTopic(declareTopic);
        return ResponseVO.success("修改成功！");
    }

    @ControllerEndpoint(operation = "导出课题申报", exceptionMessage = "导出课题申报失败")
    @PostMapping("declareTopic/excel")
    @ResponseBody
    @RequiresPermissions("declareTopic:export")
    public void export(QueryRequest queryRequest, DeclareTopic declareTopic, HttpServletResponse response) {
        List<DeclareTopicVO> declareTopics = this.declareTopicService.findDeclareTopics(queryRequest, declareTopic).getList();
        ExcelKit.$Export(DeclareTopic.class, response).downXlsx(declareTopics, false);
    }

    @ControllerEndpoint(operation = "提交意课题向申报", exceptionMessage = "提交意课题向申报失败")
    @PostMapping("declareTopic/{declareId}/preCommit")
    @ResponseBody
//    @RequiresPermissions("declareTopic:preCommit")
    public ResponseVO preApplyDeclareTopic(@PathVariable String declareId) {
        // 状态变更前的判断
        DeclareTopic beforeDeclareTopic = declareTopicService.getById(declareId);
        if(beforeDeclareTopic == null){
            return ResponseVO.failure("参数错误！");
        }
        String statusTypeCode =  beforeDeclareTopic.getStatusTypeCode();
        if(!DictEnum.NO_APPLY.getCode().equals(statusTypeCode)){
            return ResponseVO.failure("状态不正确！");
        }

        // 意向申请截止时间判断
        Topic topic = topicService.getById(beforeDeclareTopic.getTopicId());
        if(topic == null){
            return ResponseVO.failure("获取课题指南信息失败！");
        }

        TopicPlan topicPlan = topicPlanService.getById(topic.getPlanId());
        if(topicPlan == null){
            return ResponseVO.failure("获取课题计划信息失败！");
        }
        Date preApplyDate = topicPlan.getIntentionSubmitEndTime();
        if(preApplyDate == null){
            return ResponseVO.failure("请填写意向申请截止时间！");
        }
        if(DateUtil.getCurDate000() > preApplyDate.getTime()){
            return ResponseVO.failure("意向申请时间已截止！");
        }

        beforeDeclareTopic.setStatusTypeCode(DictEnum.PRE_APPLY.getCode());
        declareTopicService.updateById(beforeDeclareTopic);
        return ResponseVO.success();
    }



    @ControllerEndpoint(operation = "提交课题申报", exceptionMessage = "提交课题申报失败")
    @PostMapping("declareTopic/{declareId}/commit")
    @ResponseBody
//    @RequiresPermissions("declareTopic:commit")
    public ResponseVO applyDeclareTopic(@PathVariable String declareId) {
        // 状态变更前的判断
        DeclareTopic beforeDeclareTopic = declareTopicService.getById(declareId);
        if(beforeDeclareTopic == null){
            return ResponseVO.failure("参数错误！");
        }

        // 意向申请截止时间判断
        Topic topic = topicService.getById(beforeDeclareTopic.getTopicId());
        if(topic == null){
            return ResponseVO.failure("获取课题指南信息失败！");
        }

        TopicPlan topicPlan = topicPlanService.getById(topic.getPlanId());
        if(topicPlan == null){
            return ResponseVO.failure("获取课题计划信息失败！");
        }

        Date applyDate = topicPlan.getApplySubmitEndTime();
        if(applyDate == null){
            return ResponseVO.failure("未获取申请截止时间！");
        }
        if(DateUtil.getCurDate000() > applyDate.getTime()){
            return ResponseVO.failure("申请时间已截止！");
        }

        // 核对期次状态
        TopicPlan plan = topicPlanService.getById(topic.getPlanId());
        if(plan == null){
            throw new IllegalArgumentException("期次异常");
        }
        if(!DictEnum.PLAN_CREATE.getCode().equals(plan.getStatusCode())){
            return ResponseVO.failure("申报已结束！");
        }

        // 提交方式判断
        Configure configure = configureService.getById(plan.getConfigureId());

        // 默认为意向提交
        String businessType = DictEnum.BUSINESS_PRE_APPLY.getCode();
        if(configure != null){
            businessType = configure.getBusinessTypeCode();
        }

        String statusTypeCode =  beforeDeclareTopic.getStatusTypeCode();
        if(DictEnum.BUSINESS_NOT_PRE_APPLY.getCode().equals(businessType)){
            if(!DictEnum.NO_APPLY.getCode().equals(statusTypeCode)){
                return ResponseVO.failure("课题申报状态不正确！");
            }
        } else {
            if(!DictEnum.PRE_APPLY.getCode().equals(statusTypeCode)){
                return ResponseVO.failure("课题申报状态不正确！");
            }
        }


        beforeDeclareTopic.setStatusTypeCode(DictEnum.APPLY.getCode());
        declareTopicService.applyDeclareTopicStatusTypeCode(beforeDeclareTopic, topic.getPlanId());
        return ResponseVO.success("操作成功！");
    }


    /**
     * 资格审查详情页面
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/declareTopic/qualificationDetail/{declareId}")
    public String qualificationDetail(@PathVariable Long declareId, Model model){
        DeclareTopic declareTopic = declareTopicService.getById(declareId);
        DeclareTopicVO declareTopicVO = new DeclareTopicVO(declareTopic);
        ApplicantInfo leader = applicantInfoService.getById(declareTopic.getApplicantId());
        if(leader != null){
            declareTopicVO.setLeader(leader);
        }
        List<LogDeclareTopic> logDeclareTopics = logDeclareTopicService.findLogDeclareTopics(declareId);
        if(logDeclareTopics != null){
            declareTopicVO.setLogDeclareTopics(logDeclareTopics);
        }
        model.addAttribute("result",declareTopicVO);
        //如果是课题征集和课题指南需要关联一下

        return MyUtil.view("business/declareTopic/qualificationDetail");
    }

    /**
     * 资格审查页面
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/declareTopic/check/{declareId}")
    public String check(@PathVariable Long declareId, Model model){
        //获取通知类型字典表
        DeclareTopic declareTopic = declareTopicService.getById(declareId);
        model.addAttribute("autoCheckResult",declareTopic.getAutoCheckResult());
        model.addAttribute("declareId",declareId);
        model.addAttribute("statusTypeCode",declareTopic.getStatusTypeCode());
        return MyUtil.view("business/declareTopic/check");
    }

    @ControllerEndpoint(operation = "审查课题申报", exceptionMessage = "审查课题申报失败")
    @PostMapping("declareTopic/check/commit")
    @ResponseBody
    @RequiresPermissions("declareTopic:check")
    public ResponseVO checkDeclareTopic(DeclareTopic declareTopic) {
        DeclareTopic beforeDeclareTopic = declareTopicService.getById(declareTopic.getDeclareId());
        if(beforeDeclareTopic == null){
            throw new IllegalArgumentException("申请ID参数异常！");
        }

        // 课题状态核对
        if(!DictEnum.APPLY.getCode().equals(beforeDeclareTopic.getStatusTypeCode())){
            return ResponseVO.failure("不是已申报状态，无法审查！");
        }

        if(DictEnum.CHECK_FAILED.getCode().equals(declareTopic.getStatusTypeCode())){
            if(StringUtils.isEmpty(declareTopic.getCheckResult())){
                return ResponseVO.failure("请填写审核理由！");
            } else {
                if(declareTopic.getCheckResult().length() > 100){
                    return ResponseVO.failure("审核理由字数限制在100字以内！");
                }
            }

            // 如果资格审查不通过，该课题申请将结束
            declareTopic.setIsFinish(true);
        }

        // 期次状态核对
        DeclarePlan param = new DeclarePlan();
        param.setDeclareId(beforeDeclareTopic.getDeclareId());
        List<DeclarePlan> declarePlans = declarePlanService.findDeclarePlans(param);
        if(declarePlans == null || declarePlans.size() != 1){
            return ResponseVO.failure("申报课题数据异常！");
        }

        DeclarePlan declarePlan = declarePlans.get(0);
        TopicPlan topicPlan = topicPlanService.getById(declarePlan.getPlanId());
        if(topicPlan == null){
            return ResponseVO.failure("期次计划数据异常！");
        }
        if(!DictEnum.PLAN_CREATE.getCode().equals(topicPlan.getStatusCode())){
            return ResponseVO.failure("该期次资格审查已过！");
        }

        declareTopicService.updateCheckDeclareTopic(declareTopic);

        ApplicantInfo applicant = applicantInfoService.getById(beforeDeclareTopic.getApplicantId());
        if(applicant != null){
            messageService.sendMessageById(MessageEnum.getQualificationResultText(declareTopic.getStatusTypeCode()),getCurrentUser(), applicant.getUserId());
        }
       return ResponseVO.success("操作成功！");
    }

    @ControllerEndpoint(operation = "分配专家", exceptionMessage = "分配专家失败")
    @PostMapping("declareTopic/expert/assign")
    @ResponseBody
    @RequiresPermissions("declareTopic:assignExpert")
    public ResponseVO assignExpertForDeclareTopic(DeclareTopic declareTopic) {
        declareTopicService.updateCheckDeclareTopic(declareTopic);
        return ResponseVO.success();
    }


    @ControllerEndpoint(operation = "导出课题申报汇总表", exceptionMessage = "导出课题申报汇总表失败")
    @GetMapping("declareTopic/summary")
    @ResponseBody
    public void exportSummaryTopics(DeclareTopic declareTopic, HttpServletResponse response) {
        List<DeclareTopic> declareTopics = this.declareTopicService.findDeclareTopics(declareTopic);
        List<SummaryDeclareTopic> summaries = new ArrayList<>();
        for(DeclareTopic one:declareTopics){
           ApplicantInfo applicantInfo = applicantInfoService.getById(one.getApplicantId());
            MemberInfo param = new MemberInfo();
            param.setDeclareId(one.getDeclareId());
            List<MemberInfo> memberInfos = memberInfoService.findMemberInfos(param);
            SummaryDeclareTopic summary = new SummaryDeclareTopic(sysDictService, one, applicantInfo, memberInfos);
            summaries.add(summary);
        }
        ExcelKit.$Export(SummaryDeclareTopic.class, response).downXlsx(summaries, false);
    }

    @ControllerEndpoint(operation = "导出课题意向登记表", exceptionMessage = "导出课题意向登记表失败")
    @GetMapping("declareTopic/intention")
    @ResponseBody
    public void exportIntentionForm(DeclareTopic declareTopic, HttpServletResponse response) {
        List<DeclareTopic> declareTopics = this.declareTopicService.findDeclareTopics(declareTopic);
        Map<String, List<SummaryDeclareTopic>> summaries = new HashMap();
        for(DeclareTopic one:declareTopics){
            ApplicantInfo applicantInfo = applicantInfoService.getById(one.getApplicantId());
            MemberInfo param = new MemberInfo();
            param.setDeclareId(one.getDeclareId());
            List<MemberInfo> memberInfos = memberInfoService.findMemberInfos(param);
            SummaryDeclareTopic summary = new SummaryDeclareTopic(sysDictService, one, applicantInfo, memberInfos);
            Topic topic = topicService.getById(one.getTopicId());
            List<SummaryDeclareTopic> lstSummaries = summaries.get(topic.getTopicName());
            if(lstSummaries == null) {
                lstSummaries = new ArrayList();
            }
            lstSummaries.add(summary);
            summaries.put(topic.getTopicName(), lstSummaries);
        }
        Template template = templateService.findByTemplateTypeCode(DictEnum.TEMPLATE_INTENTION.getCode());
        if(template == null){
            throw new RuntimeException("模板文件不存在！");
        }
        SysFile sysFile = sysFileService.getById(template.getFileId());
        if(sysFile == null){
            throw new RuntimeException("模板文件不存在！");
        }
        try {
            FileUtil.downloadExcel(ExportExcelService.exportIntentionForm(summaries, declareTopic.getYearSearch(), sysFile.getUrl()), response, URLEncoder.encode("filename11", "UTF-8"));
        } catch (Exception e) {
            throw new RuntimeException("下载失败！");
        }
    }


    @GetMapping("declareTopic/{planId}/unusedEntrusts")
    @ResponseBody
//    @RequiresPermissions("declareTopic:list")
    public ResponseVO chooseEntrusts(QueryRequest request, @PathVariable("planId") Long planId) {
        if(planId == null ){
            return ResponseVO.failure("参数异常！");
        }
        PageInfo<SelectEntrustVO> pageInfo =  this.declareTopicService.chooseEntrusts(request, planId);
        return ResponseVO.success(pageInfo);
    }

    @GetMapping("declareTopic/{planId}/assignEntrusts")
    @ResponseBody
//    @RequiresPermissions("declareTopic:list")
    public ResponseVO assignEntrusts(QueryRequest request, @PathVariable("planId") Long planId) {
        if(planId == null ){
            return ResponseVO.failure("参数异常！");
        }
        PageInfo<SelectEntrustVO> pageInfo =  this.declareTopicService.assignEntrusts(request, planId);
        return ResponseVO.success(pageInfo);
    }

    @ControllerEndpoint(operation = "下载委托课题申请书", exceptionMessage = "下载失败")
    @GetMapping("exportEntrustPreItemApply/{declareId}")
    public void exportEntrustPreItemApply(@PathVariable("declareId") Long declareId, HttpServletResponse response) {
        this.declareTopicService.exportEntrustPreItemApply(declareId, response);
    }

    @ControllerEndpoint(operation = "下载结项申请书", exceptionMessage = "下载失败")
    @GetMapping("exportEntrustConclusionApply/{declareId}")
    public void ConclusionEntrustApply(@PathVariable("declareId") Long declareId, HttpServletResponse response) {

       this.declareTopicService.ConclusionEntrustApply(declareId, response);
    }
    @ControllerEndpoint(operation = "下载延期申请书", exceptionMessage = "下载失败")
    @GetMapping("exportDelayApply/{declareId}")
    public void exportDelayApply(@PathVariable("declareId") Long declareId, HttpServletResponse response) {

        this.declareTopicService.exportDelayApply(declareId, response);
    }

    @ControllerEndpoint(operation = "下载结项证书", exceptionMessage = "下载失败")
    @GetMapping("exportCertificate/{declareId}")
    public void exportCertificate(@PathVariable("declareId") Long declareId, HttpServletResponse response) {

        this.declareTopicService.exportCertificate(declareId, response);
    }
    @ControllerEndpoint(operation = "下载立结项通知书", exceptionMessage = "下载失败")
    @GetMapping("exportNotice/{declareId}")
    public void exportNotice(@PathVariable("declareId") Long declareId, HttpServletResponse response) {

        this.declareTopicService.exportNotice(declareId, response);
    }

}
